﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Citrix.Cmp;
using System.Windows;

namespace SkinningSample.ViewModel
{
    /// <summary>
    /// This class manages the appearance of the application by swapping its skin based on the
    /// type of the client device the user is using to access this app. When they are using an
    /// Android device we use the Android skin. For all other devices/clients we use the iOS
    /// skin.
    /// </summary>
    internal class Skinning
    {
        /// <summary>
        /// Modes used to override which skin is used.
        /// </summary>
        public enum SkinOverrideMode
        {
            /// <summary>
            /// The default, we detect the client OS and set the skin based on the client.
            /// </summary>
            Auto,

            /// <summary>
            /// Force the skin to the Android skin.
            /// </summary>
            Android,

            /// <summary>
            /// Force the skin to the iOS skin.
            /// </summary>
            iOS
        }

        /// <summary>
        /// The current skin override mode.
        /// </summary>
        private SkinOverrideMode _mode = SkinOverrideMode.Auto;

        /// <summary>
        /// A reference to the app object.
        /// </summary>
        private readonly App _app;

        /// <summary>
        /// This resource dictionary holds all of our Android specific resources.
        /// </summary>
        private ResourceDictionary _androidResources = new ResourceDictionary();
        
        /// <summary>
        /// This resource dictionary holds all of our iOS specific resources.
        /// </summary>
        private ResourceDictionary _iOSResources = new ResourceDictionary();

        /// <summary>
        /// Constructor.
        /// </summary>
        /// <param name="app">A reference to the app instance we belong to.</param>
        /// <exception cref="ArgumentNullException">Thrown if app is null.</exception>
        public Skinning(App app)
        {
            if (null == app)
            {
                throw new ArgumentNullException("app");
            }

            _app = app;

            // Load both sets of skin resources that we support.
            this._androidResources.Source = new Uri("pack://application:,,,/SkinAndroid/AndroidSkin.xaml");
            this._iOSResources.Source = new Uri("pack://application:,,,/SkinIOS/iOsSkin.xaml");

            _app.CmpWpfApi.SessionManager.SessionConnected += new EventHandler<Citrix.Cmp.SessionConnectedArgs>(SessionManager_SessionConnected);
            
            // Set the initial skin at app startup.
            ApplySkin(_app.CmpWpfApi.SessionManager.GetClientState().DeviceOs);
        }

        /// <summary>
        /// Used to configure the skin override mode.
        /// </summary>
        public SkinOverrideMode SkinMode
        {
            get
            {
                return _mode;
            }
            set
            {
                if (value != _mode)
                {
                    _mode = value;
                    if (SkinOverrideMode.Android == _mode)
                    {
                        ApplySkin(DeviceOS.Android);
                    }
                    else if (SkinOverrideMode.iOS == _mode)
                    {
                        ApplySkin(DeviceOS.iOs);
                    }
                    else
                    {
                        ApplySkin(_app.CmpWpfApi.SessionManager.GetClientState().DeviceOs);
                    }
                }
            }
        }

        /// <summary>
        /// Event handler for the Citrix session being re-established. The user may be accessing
        /// the app from a different device that requires a different skin. So check the client
        /// state and configure the appropriate skin.
        /// </summary>
        /// <param name="sender">Not used.</param>
        /// <param name="e">Contains the client state.</param>
        private void SessionManager_SessionConnected(object sender, Citrix.Cmp.SessionConnectedArgs e)
        {
            if (_mode == SkinOverrideMode.Auto)
            {
                ApplySkin(e.NewState.DeviceOs);
            }
        }

        /// <summary>
        /// Applies the appropriate skin based on the supplied client OS state. We use the
        /// Android skin on Android devices. For all others we use the iOS skin.
        /// </summary>
        /// <param name="deviceOs">The device operating system.</param>
        private void ApplySkin(DeviceOS deviceOs)
        {
            //
            // Note: we load the new skin before unloading the old one. This prevents a brief
            // flash of white where controls have no skin colors loaded.
            //
            if (deviceOs == DeviceOS.Android)
            {
                _app.Resources.MergedDictionaries.Add(this._androidResources);
                _app.Resources.MergedDictionaries.Remove(this._iOSResources);
            }
            else
            {
                _app.Resources.MergedDictionaries.Add(this._iOSResources);
                _app.Resources.MergedDictionaries.Remove(this._androidResources);
            }
        }
    }
}
